package com.test.service.impl;

import com.test.entity.File;
import com.test.entity.User;
import com.test.mapper.FileMapper;
import com.test.service.FileService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@Transactional
public class FileServiceImpl implements FileService {
    @Autowired
    private FileMapper fileMapper;

    /**
     * 根据用户的id查询当前用户下的所有上传的文件  pageHelper进行分页
     *
     * @param userId
     */
     //没有传每页大小参数,所以此处定义参数测试
    @Value("${pageSize}")
    private Integer pageSize;
    @Override
    public List<File> findFiles(Integer userId) {
        //分页只需要在查询的数据前设置当前页和每页大小即可,也有默认值
        PageHelper.startPage(1, pageSize);
        List<File> files = fileMapper.findFiles(userId);
        return files;
    }

    /**
     * 根据用户id保存用户上传的文件信息
     *
     * @param file
     */
    @Override
    public void saveFile(MultipartFile file, HttpSession session) throws IOException {
        User user = (User) session.getAttribute("user");
        //获取文件的名称 旧名称
        String oldFileName = file.getOriginalFilename();

        //文件的后缀名, 用到FilenameUtils工具类 ,获取的扩展名
        String extensionName = "." + FilenameUtils.getExtension(oldFileName);

        //文件的新名称 时间戳加上随机数 加上后缀名
        String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + UUID.randomUUID().toString().replace("-", "") + extensionName;

        //文件大小
        long fileSize = file.getSize();

        //文件类型
        String fileType = file.getContentType();

        //文件储存的路径  在resorce目录下的static/files
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";
        //根据日期生成文件夹储存文件
        String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dateDirPath = realPath + "/" + dateFormat;

        java.io.File dateDir = new java.io.File(dateDirPath);
        //如果日文文件夹不存在就创建文件夹
        if (!dateDir.exists()) {
            dateDir.mkdirs();
        }
        //储存复制文件,储存
        file.transferTo(new java.io.File(dateDir, newFileName));

        //文件信息储存到数据库
        File files = new File();
        files.setOldFileName(oldFileName);
        files.setNewFileName(newFileName);
        files.setExt(extensionName);
        files.setPath("/files/" + dateFormat);
        files.setSize(String.valueOf(fileSize));
        files.setType(fileType);
        //是否为图片,文具文件类型获取,如果是图片的话,文件类型是以image开头的
        String isImage = fileType.startsWith("image") ? "是" : "否";
        files.setIsImage(isImage);

        //上传日期
        files.setUploadTime(new Date());

        //用户id
        files.setUserId(user.getId());
        fileMapper.saveFile(files);
    }

    /**
     * 文件下载
     *
     * @param id 文件id
     */
    @Override
    public void findByFileId(Integer id, String openStyle, HttpServletResponse response) throws IOException {
        //判断是否携带openStyle,如果没有下载就是附件下载,有携带的话就是携带的inline ,也可都携带参数,此处做判断即可
        String download_or_Inline = openStyle == null ? "attachment" : openStyle;
        File fileDb = fileMapper.findByFileId(id);
        if (fileDb != null) {
            //先获取项目所在绝对路径    //获取文件储存的文件夹 以及文件的名称
            String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + fileDb.getPath();
            //通过新文件名得到文件
            String newFileName = fileDb.getNewFileName();
            //给用户的是之前的文件名
            String oldFileName = fileDb.getOldFileName();
            //输入流
            FileInputStream is = new FileInputStream(new java.io.File(realPath, newFileName));

            //做判断,如果是图片才能在线打开,不是图片只能下载
            if (download_or_Inline.equals("inline") && !fileDb.getType().startsWith("image")) {
                //附件只能进行下载
                response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(oldFileName, "utf-8"));
            } else {
                //附件下载  inline是在线打开  attachment 是附件下载
                response.setHeader("content-disposition", download_or_Inline+";filename=" + URLEncoder.encode(oldFileName, "utf-8"));
            }
            //文件输出,响应回去的,添加response
            ServletOutputStream os = response.getOutputStream();
            //文件复制  调用IOUtils工具类直接复制
            IOUtils.copy(is, os);

            //在线打开,不计下载次数
            if (download_or_Inline.equals("attachment")) {
                //文件复制之后,下载次数 + 1
                fileDb.setDownCounts(fileDb.getDownCounts() + 1);
                //将修改后的下载数量跟新到数据库
                fileMapper.updateDownloadCounts(fileDb);
            }

            //关闭流 释放资源
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }
    }

    /**
     * 根据id删除文件
     * @param id
     */
    @Override
    public void deleteFile(Integer id) throws FileNotFoundException {
        //删除文件,要先查到文件信息,删除储存的文件,然后删除数据库文件信息
        File fileDb = fileMapper.findByFileId(id);
        //获取文件的位置   文件储存的位置:  resource(本项目下)     /sttic/siles/xxxxxx.jsp
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "static";
        //获取文件
        java.io.File file = new java.io.File((realPath), fileDb.getNewFileName());
        //判断如果文件存在就删除,不存在不要重复操作
        if (file.exists()) {
            file.delete();
        }

        //删除数据库中的文件信息
        fileMapper.deleteFile(id);
    }
}
